﻿using WH.Contracts.Dtos;
using WH.Contracts.Systems.Users;
using WH.Model.Enums;
using WH.Model.Systems;
using WH.Repositories.IRepositories.ISystem;
using WH.Repositories.IRepositories.System;
using WH.Services.BaseService;
using WH.Services.IServices.ISystem;
using Rw.Core.Common;
using Rw.Core.Common.Paging;
using WH.Common.Constant;
using WH.Common.CustomException;
using WH.Common.Paging;
using WH.Common.DbConfig;
using WH.Common.Cache;
using System.Linq.Expressions;

namespace WH.Services.Services.System
{
    public class UserService : BaseService<UserEntity>, IUserService
    {
        private readonly IUserRepository _userRepository;
        //private readonly ISysConfigRepository _sysConfigRepository;
        private readonly IUserLogonRepository _userLogonRepository;

        private readonly ICaching _caching;
        public UserService(
            IUserRepository userRepository,
            //ISysConfigRepository sysConfigRepository,
            IUserLogonRepository userLogonRepository,
            ICaching caching
            ) : base(userRepository)
        {
            _userRepository = userRepository;
            _userLogonRepository = userLogonRepository;
            //_sysConfigRepository = sysConfigRepository;
            _caching = caching;
        }

        public async Task<int> AddLogonCount(UserEntity entity)
        {
            entity.LogonCount += 1;
            return await _userRepository.AddLogonCount(entity);
        }
        /// <summary>
        /// 校验用户名密码
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="passWord"></param>
        /// <returns></returns>
        public async Task<ResultResponse<UserEntity>> CheckLoginAsync(string userName, string passWord)
        {
            var result = new ResultResponse<UserEntity>() { Msg = "登录成功" };

            var entity = await _userRepository.NoFilter().FirstOrDefaultAsync(t => t.Account.Equals(userName));
            if (entity == null)
            {
                //TODO: 安全考虑是否要改成账户或密码不正确？
                throw new BadRequestException("账户或密码不正确");// "账户不存在，请重新输入";
            }

            if (!entity.IsEnable)
            {
                throw new BadRequestException("账户被系统锁定,请联系管理员");
            }

            //var data = await _configService.FirstOrDefaultAsync();
            var configs = new DatabaseConfigurationProvider();


            var logOnEntity = await _userLogonRepository.NoFilter().FirstOrDefaultAsync(t => t.Id.Equals(entity.Id));

            if (logOnEntity is null)
            {
                throw new BadRequestException("账户或密码不正确");
            }

            var UNLOCKTIME = int.Parse(configs["UNLOCKTIME"]?.Value ?? "5");
            var CHANGECYCLE = int.Parse(configs["CHANGECYCLE"]?.Value ?? "30");
            var ADVENT = int.Parse(configs["ADVENT"]?.Value ?? "7");
            var TRIALTIMES = int.Parse(configs["TRIALTIMES"]?.Value ?? "7");

            var key = $"{BusinessFunction.TrialTimes}:{entity.Id}";

            var passRedis = _caching.Get<PassWordDtos>(key);

            if (passRedis is not null && passRedis.Count >= TRIALTIMES && DateTime.Now <= passRedis.Time)
            {
                throw new BadRequestException($"您的帐户已锁定，请联系管理员解锁或者等待解锁时间结束,锁定时长{UNLOCKTIME}分钟");
            }

            var dbPassword = Md5.MD5Hash(DESEncrypt.Encrypt(passWord.ToLower(), logOnEntity.SecretKey).ToLower()).ToLower();

            if (dbPassword.Equals(logOnEntity.Password))
            {
                if (!entity.IsAdministrator && entity.AccessType == (int?)UserAccessTypeEnum.System)
                {
                    //判断密码周期
                    var MyDateTime = logOnEntity.UpdatedTime ?? DateTime.Now;
                    var ts = DateTime.Now - MyDateTime;

                    //var logonConfig = await _configService.FirstOrDefaultAsync();

                    var diff = CHANGECYCLE - ts.Days;

                    if (CHANGECYCLE < ts.Days)
                    {
                        throw new BadRequestException("您的帐户已过期，请联系管理员修改密码");
                    }

                    if (diff <= ADVENT)
                    {
                        result.Msg = $"距离更换密码周期仅剩{diff}天,请及时更换密码";
                    }
                }
            }
            else
            {
                if (!entity.IsAdministrator && entity.AccessType == (int?)UserAccessTypeEnum.System)
                {
                    //if (passRedis is not null && DateTime.Now <= passRedis.Time)
                    //{
                    //    throw new BadRequestException($"您的帐户已锁定，请联系管理员解锁或者等待解锁时间结束,锁定时长{UNLOCKTIME}分钟");
                    //}

                    if (passRedis is not null)
                    {
                        passRedis.Count = passRedis.Count + 1;

                        if (passRedis.Count >= TRIALTIMES)
                        {
                            passRedis.Time = DateTime.Now.AddMinutes(UNLOCKTIME);

                            //_caching.Remove(key);
                            _caching.Add(key, passRedis, TimeSpan.FromMinutes(UNLOCKTIME));

                            throw new BadRequestException($"您的帐户已锁定，请联系管理员解锁或者等待解锁时间结束,锁定时长{UNLOCKTIME}分钟");
                        }
                        else
                        {
                            //_caching.Remove(key);
                            _caching.Add(key, passRedis, TimeSpan.FromMinutes(UNLOCKTIME));
                            //,请重新输入,您还有一次次机会,再次错误两次，账户将锁定{data.UnlockTime}分钟";
                            throw new BadRequestException($"账户或密码不正确");
                        }
                    }
                    else
                    {
                        _caching.Add(key, new PassWordDtos { Count = 1, Id = entity.Id }, TimeSpan.FromMinutes(UNLOCKTIME));
                    }

                    //await _userLogOnRepository.UpdateAsync(logOnEntity);

                }
                else
                {
                    //,请重新输入,您还有两次机会,再次错误两次，账户将锁定{data.UnlockTime}分钟";      
                    //throw new BadRequestException("账户或密码不正确");
                }

                throw new BadRequestException("账户或密码不正确");
            }


            //登录成功就删除一下错误记录信息
            _caching.Remove(key);

            await AddLogonCount(entity);

            result.IsSucceed = true;
            result.Data = entity;

            return result;
        }

        public async Task<bool> ExistsNoFilterAsync(Expression<Func<UserEntity, bool>> predicate)
        {
            return await _userRepository.NoFilter().ExistsAsync(predicate);
        }

        public async Task<bool> ExistsUserAsync(string? account)
        {
            return await _userRepository.NoFilter().ExistsAsync(x => x.Account == account);
        }

        public async Task<int> GetLogonCountAsync()
        {
            return await _userRepository.SumAsync(x => x.LogonCount);
        }

        public async Task<UserEntity> GetUser(string id)
        {
            return await _userRepository.FindByIdAsync(id);
        }

        public async Task<IPagedList<UserEntity>> GetUsersByPageAsync(PageParam pager, UserFilter filter)
        {
            return await _userRepository.GetUsersByPageAsync(pager, filter);
        }
    }
}
